#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
Author: FQ
Module Description: minister_utils ...
File: minister_utils.py
Date: 2019/3/5
"""
from pyshare.dal.repository_impl import MinisterRepository, MinisterGroupRepository
from pyshare.bll.utils.cross.prince_utils import CrownPrince
from pyshare.const.enums.minister import MinisterGroup
from pyshare.dal.gameconfig.query import getProfile, getProfileList


class Minister(object):

    @staticmethod
    def get_fight_power(aptitude, attribute, lv):
        """
        获得大臣战力

        公式: (大臣总资质 * 等级) ** 0.9 + 0.1 * 大臣总属性 ** 0.9

        :param int aptitude: 大臣总资质
        :param int attribute: 大臣总属性
        :param int lv: 大臣等级
        :return: 战力
        :rtype: int
        """
        return int((aptitude * lv) ** 0.9 + 0.1 * attribute ** 0.9)

    @staticmethod
    def sum_minister_attr(attr_list):
        """
        把大臣属性字典列表转换为列表

        :param list attr_list: 大臣属性字典列表。eg. [{商}, {农}, {政}, {军}]
        :return: [商,农,政,军]
        :rtype: list
        """
        return map(lambda attr_dict: sum(attr_dict.itervalues()), attr_list)

    @classmethod
    def calculate_single_minister_attr(cls, rid, minister, need_sum=False, for_fight=False):
        """
        返回大臣属性数组

        .. versionchanged:: 1.0
           修复清帝带来buff的问题

        .. versionchanged:: 1.4
           增加官品buff

        :param str rid: 角色id
        :param minister: 大臣实例
        :type minister: MinisterAdapter
        :param bool need_sum: 控制是获取综合值还是获取数组字典
        :param bool for_fight: 是否用于计算战力、血量V1.9
        :return:[商,农,政,军]
        :rtype: list
        """
        attr_list = minister.attribute

        # 进行属性汇总: [商,农,政,军]
        if need_sum:
            attr_list = cls.sum_minister_attr(attr_list)

            # 计算战力等太子增加皇子属性V1.9
            if for_fight and (minister.cfg_id == 100):
                attr_list = CrownPrince.add_prince_attribute(rid, attr_list)

        return attr_list

    @classmethod
    def calculate_minister_fight_power(cls, rid, minister):
        """
        计算大臣战斗力

        :param str rid: 角色id
        :param minister: 大臣实例
        :type minister: MinisterAdapter
        :return: 战斗力
        :rtype: int
        """
        aptitude = sum(map(lambda d: sum(d.itervalues()), minister.aptitude))
        attribute = sum(cls.calculate_single_minister_attr(rid, minister,
                                                           need_sum=True,
                                                           for_fight=True))

        return cls.get_fight_power(aptitude, attribute, minister.lv)

    @classmethod
    def get_role_fight_power(cls, rid):
        """
        获取个人战力
        :param rid:
        :return:
        """
        fight = 0
        minister_list = MinisterRepository.filter_by_rid(rid)
        # 计算单个大臣战力
        for minister in minister_list:
            rid = minister.role_guid
            fight += cls.calculate_minister_fight_power(rid, minister)

        return fight

    @classmethod
    def get_many_role_fight_power_average(cls, rid_list, min_power=10000):
        """
        获取多个角色战力平均值
        :param rid_list:
        :param min_power: 过滤条件 最小战力值
        :return: {rid: power}
        """
        from collections import defaultdict
        power_dict = defaultdict(int)

        minister_list = MinisterRepository.filter_attribute_by_rid_list(rid_list)
        # 计算单个大臣战力
        rid_set = set([])
        for minister in minister_list:
            rid = minister.role_guid
            rid_set.add(rid)
            power_dict[rid] += cls.calculate_minister_fight_power(rid, minister)
        count = 0
        num = 0
        for rid, fight_power in power_dict.iteritems():
            if fight_power < min_power:
                continue
            num += 1
            count += fight_power
        if num == 0:
            return 0
        return int(count / num)

    @classmethod
    def get_many_role_max_minister_fight_power_average(cls, rid_list):
        """
        获取多个角色最强大臣战力平均值
        :param rid_list:
        :return: {rid: power}
        """
        role_dict = dict()
        minister_list = MinisterRepository.filter_attribute_by_rid_list(rid_list)
        # 获取玩家的最强大臣
        for minister in minister_list:
            # 计算大臣战力值
            fight_power = cls.calculate_minister_fight_power(minister.role_guid, minister)
            if minister.role_guid not in role_dict:
                role_dict[minister.role_guid] = fight_power
            if role_dict[minister.role_guid] < fight_power:
                role_dict[minister.role_guid] = fight_power
        # 取平均值
        count, num = 0, 0
        for k, fight_power in role_dict.iteritems():
            if fight_power < 1:
                continue
            count += 1
            num += fight_power
        if num == 0:
            return 0
        return int(num / count)

    @staticmethod
    def get_minister_talent_activity_buff(rid, minister_id_list, activity_class,
                                          activity_type, talent_type,
                                          group_id=MinisterGroup.StarEmperor.value):
        """
        获取大臣对应的活动天赋战力加成

        用法:
            * 自身战力加成天赋,取对应大臣加成值
            * 全队战力加成天赋,取所有大臣最大加成值

        :param list(int) minister_id_list: 大臣列表
        :param int activity_class: 活动大类
        :param int activity_type: 活动小类
        :param int talent_type: 天赋类型
        :param int group_id: 大臣组id
        :return: 大臣战力加成, 1为没加成
        :rtype: dict(int)
        """
        group_cfgs = getProfileList('TcMinisterGroup', GroupId=group_id)
        # 大臣组成员id
        group_cfg_ids = [group_cfg.MinisterId for group_cfg in group_cfgs]

        # 拥有大臣组数据
        group_data = MinisterGroupRepository.get_by_rid_groupid(rid, group_id)

        # 活动类天赋配置
        talent_activity_cfg = getProfile(
            "TcMinisterTalentActivity",
            TalentType=talent_type,
            ActivityClass=activity_class,
            ActivityType=activity_type,
        )

        result = {}

        for minister_id in minister_id_list:

            # 大臣不属于大臣组
            if minister_id not in group_cfg_ids:
                result[str(minister_id)] = 1.0
                continue

            # 大臣不属于指定活动大臣
            if (not talent_activity_cfg) or (minister_id not in talent_activity_cfg.MinisterIdList):
                result[str(minister_id)] = 1.0
                continue

            # 强化等级
            strengthen_lv = group_data.strengthen_lv.get(str(minister_id))
            # 已解锁的天赋列表
            talent_list = group_data.talent.get(str(minister_id), [])

            # 未解锁对应天赋
            if talent_type not in talent_list:
                result[str(minister_id)] = 1.0
                continue

            talnet_activity_buff_cfgs = getProfileList(
                "TcMinisterTalentActivityBuff",
                order_by="-StrengthenLv",
                TalentType=talent_type,
                StrengthenLv__lte=strengthen_lv,
            )

            # 没有对应的加成配置
            if not talnet_activity_buff_cfgs:
                result[str(minister_id)] = 1.0
                continue

            buff_cfg = talnet_activity_buff_cfgs[0]
            result[str(minister_id)] = 1.0 + buff_cfg.AddPercent

        return result

    @staticmethod
    def get_talent_buff(self_talent_buff, team_talent_buff, minister_id):
        """
        获取单个大臣的天赋加成值
        """
        self_buff = 0.0
        team_buff = 0.0

        if self_talent_buff:
            self_buff = self_talent_buff.get(str(minister_id), 1.0) - 1.0

        if team_talent_buff:
            team_buff = max(team_talent_buff.values()) - 1.0

        return self_buff + team_buff
